#include <Viewer/Camera.hpp>
#include <math.h>

#define PI 3.14159265
#define FACTEUR 100

#define ANGLE_INCREMENT ( (float)PI / 9 )
#define DISTANCE_INCREMENT 0.5f



namespace Viewer
{
	Camera::Camera(float x, float y, float z ) : position(x,y,z), angleXY(0), angleXZ(0)
	{
		
	}

	Camera::~Camera()
	{

	}

	Vector Camera::GetPosition( )
	{
		return position;
	}

	float Camera::GetAngleXZ( )
	{
		return angleXZ;
	}

	float Camera::GetAngleXY( )
	{
		return angleXY;
	}
			
	Vector Camera::GetDirection()
	{
		Vector direction;
		
		// Calcul de la position relative du vecteur de direction
		direction.x = (float)( cos( angleXY ) * cos( angleXZ ) );
		direction.y = (float)sin( angleXY );
		direction.z = - (float)( cos( angleXY ) * sin( angleXZ ) );
		
		return direction;

	}

	Vector Camera::GetVertical()
	{
		Vector vertical;

		// Calcul de la position relative du vecteur d'indication de vertical
		vertical.x = (float)( cos( angleXY + PI/2 ) * cos( angleXZ ) );
		vertical.y = (float)sin( angleXY + PI/2 );
		vertical.z = - (float)( cos( angleXY + PI/2 ) * sin( angleXZ ) );

		return vertical;
	}

	void Camera::MoveUp()
	{
		Vector vertical = GetVertical();
				
		position.x += vertical.x * DISTANCE_INCREMENT;
		position.y += vertical.y * DISTANCE_INCREMENT;
		position.z += vertical.z * DISTANCE_INCREMENT;
	}

	void Camera::MoveDown()
	{
		Vector vertical = GetVertical();

		position.x -= vertical.x * DISTANCE_INCREMENT;
		position.y -= vertical.y * DISTANCE_INCREMENT;
		position.z -= vertical.z * DISTANCE_INCREMENT;
	}

	void Camera::MoveLeft()
	{
		Vector ortho = GetDirection().Cross( GetVertical() );
		
		ortho.Normalize();

		position.x -= ortho.x * DISTANCE_INCREMENT;
		position.y -= ortho.y * DISTANCE_INCREMENT;
		position.z -= ortho.z * DISTANCE_INCREMENT;
	}

	void Camera::MoveRight()
	{
		Vector ortho = GetDirection().Cross( GetVertical() );
		
		ortho.Normalize();

		position.x += ortho.x * DISTANCE_INCREMENT;
		position.y += ortho.y * DISTANCE_INCREMENT;
		position.z += ortho.z * DISTANCE_INCREMENT;
	}

	void Camera::ZoomIn()
	{
		Vector direction = GetDirection();

		position.x += direction.x * DISTANCE_INCREMENT;
		position.y += direction.y * DISTANCE_INCREMENT;
		position.z += direction.z * DISTANCE_INCREMENT;
	}

	void Camera::ZoomOut()
	{
		Vector direction = GetDirection();

		position.x -= direction.x * DISTANCE_INCREMENT;
		position.y -= direction.y * DISTANCE_INCREMENT;
		position.z -= direction.z * DISTANCE_INCREMENT;
	}

	void Camera::Move(int x, int y)
	{
		angleXY -= ( y / (float)FACTEUR ) * ANGLE_INCREMENT;
		angleXZ -= ( x / (float)FACTEUR ) * ANGLE_INCREMENT;
	} 

	void Camera::Reset( float x, float y, float z )
	{
		angleXY = 0;
		angleXZ = 0;

		position.x = x;
		position.y = y;
		position.z = z;
	}
}
